﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Workflow;
using System.Web.Services.Protocols;

namespace CrmContrib.Workflow.Activities.Invoicing
{
    [CrmWorkflowActivity("Find contact by email", "CrmContrib \\ Invoicing")]
    public class FindContactByEmailActivity : Activity
    {

        [CrmInput("Email")]
        [ValidationOption(ValidationOption.Required)]
        public String Email
        {
            get { return (String)base.GetValue(EmailProperty); }
            set { base.SetValue(EmailProperty, value); }
        }

        public static readonly DependencyProperty EmailProperty = DependencyProperty.Register("Email", typeof(String), typeof(FindContactByEmailActivity));


        private Guid LoadContact(ICrmService crmService, Guid customerId)
        {
            var projection = new ColumnSet();
            projection.Attributes.Add("contactid");

            var target = new TargetRetrieveContact { EntityId = customerId };
            try
            {
                var response = (RetrieveResponse)crmService.Execute(new RetrieveRequest { ColumnSet = projection, Target = target, ReturnDynamicEntities = true });
                DynamicEntity contact = (DynamicEntity)response.BusinessEntity;
                if (contact.Properties.Contains("contactid"))
                {
                    HasAContact = new CrmBoolean(true);
                    return ((Key)contact["contactid"]).Value;
                }
            }
            catch (SoapException)
            {
                HasAContact = new CrmBoolean(false);
            }
            return Guid.Empty;
        }

        private IEnumerable<Guid> LoadContactWithEmail(ICrmService crmService, String email)
        {
            //Get the opportunity relationship for the opportunity with the given customer role
            ConditionExpression conditionEmailOne = new ConditionExpression();
            conditionEmailOne.AttributeName = "emailaddress1";
            conditionEmailOne.Operator = ConditionOperator.Equal;
            conditionEmailOne.Values = new string[] { email };

            ConditionExpression conditionEmailTwo = new ConditionExpression();
            conditionEmailTwo.AttributeName = "emailaddress2";
            conditionEmailTwo.Operator = ConditionOperator.Equal;
            conditionEmailTwo.Values = new string[] { email };

            ConditionExpression conditionEmailThree = new ConditionExpression();
            conditionEmailThree.AttributeName = "emailaddress3";
            conditionEmailThree.Operator = ConditionOperator.Equal;
            conditionEmailThree.Values = new string[] { email };

            FilterExpression combineConditions = new FilterExpression();
            combineConditions.FilterOperator = LogicalOperator.Or;
            combineConditions.AddCondition(conditionEmailOne);
            combineConditions.AddCondition(conditionEmailTwo);
            combineConditions.AddCondition(conditionEmailThree);

            QueryExpression contactQuery = new QueryExpression();
            contactQuery.ColumnSet = new AllColumns();
            contactQuery.EntityName = EntityName.contact.ToString();
            contactQuery.Criteria = combineConditions;

            //get the customer account/contact id
            BusinessEntityCollection response = crmService.RetrieveMultiple(contactQuery);
            foreach (Object item in response.BusinessEntities)
            {
                contact myContact = new contact();
                myContact = (contact)item;
                yield return myContact.contactid.Value;
            }
        }

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            var contextService = executionContext.GetService<IContextService>();
            var workflowContext = contextService.Context;
            var crmService = workflowContext.CreateCrmService();
            var customers = LoadContactWithEmail(crmService, Email);

            HasAContact = new CrmBoolean(false);

            Guid myContact = customers.FirstOrDefault();
            if (myContact != Guid.Empty)
                Contact = new Lookup("contact", myContact);

            return base.Execute(executionContext);
        }

        [CrmOutput("Contact")]
        [CrmReferenceTarget("contact")]
        public Lookup Contact
        {
            get { return (Lookup)base.GetValue(ContactProperty); }
            set { base.SetValue(ContactProperty, value); }
        }

        public static readonly DependencyProperty ContactProperty = DependencyProperty.Register("Contact", typeof(Lookup), typeof(FindContactByEmailActivity));

        [CrmOutput("Has a contact")]
        public CrmBoolean HasAContact
        {
            get { return (CrmBoolean)base.GetValue(HasAContactProperty); }
            set { base.SetValue(HasAContactProperty, value); }
        }

        public static readonly DependencyProperty HasAContactProperty = DependencyProperty.Register("HasAContact", typeof(CrmBoolean), typeof(FindContactByEmailActivity));

    }
}
